﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using CSLauncher.Hotkey.Interface;

namespace CSLauncher.Hotkey
{
    internal class WindowsHotkeyManager : Form, IHotkeyManager
    {
        [DllImport("user32.dll")]
        private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
    
        [DllImport("user32.dll")]
        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

        private readonly Dictionary<int, HotkeyData> hotkeyList;
            
        public WindowsHotkeyManager()
        {
            hotkeyList = new Dictionary<int, HotkeyData>();
        }
        
        [Flags]
        private enum WindowsHotkeyModifieds
        {
            None = 0,
            Alt = 1,
            Ctrl= 2,
            Shift = 4,
            Win = 8,
        }

        public HotkeyData this[int identifier]
        {
            get { return hotkeyList[identifier]; }
        }

        public ICollection<int> RegisteredIdentifiers
        {
            get { return hotkeyList.Keys; }
        }

        public bool IdentifierRegistered(int identifier)
        {
            return hotkeyList.ContainsKey(identifier);
        }

        public void Register(int identifier, HotkeyData hotkey)
        {
            WindowsHotkeyModifieds keyModifiers = WindowsHotkeyModifieds.None;

            if (hotkey.Alt)
            {
                keyModifiers |= WindowsHotkeyModifieds.Alt;
            }

            if (hotkey.Ctrl)
            {
                keyModifiers |= WindowsHotkeyModifieds.Ctrl;
            }

            if (hotkey.Shift)
            {
                keyModifiers |= WindowsHotkeyModifieds.Shift;
            }

            if (hotkey.Winkey)
            {
                keyModifiers |= WindowsHotkeyModifieds.Win;
            }

            if (!RegisterHotKey(Handle, identifier, (uint)keyModifiers, (uint)hotkey.Key))
            {
                throw new HotkeyRegistrationFailedException();
            }

            if (hotkeyList.ContainsKey(identifier))
            {
                hotkeyList[identifier] = hotkey;
            }
            else
            {
                hotkeyList.Add(identifier, hotkey);    
            }
        }

        public HotkeyData Get(int identifier)
        {
            return hotkeyList[identifier];
        }

        public void Remove(int identifier)
        {
            if (!hotkeyList.ContainsKey(identifier))
            {
                return;
            }

            UnregisterHotKey(Handle, identifier);
            hotkeyList.Remove(identifier);
        }

        protected override void WndProc(ref Message m)
        {
            if (m.Msg == 0x312) // this is WM_HOTKEY
            {
                EventHandler<HotkeyPressedEvent> e = HotkeyPressed;
                if (e != null)
                {
                    e(this, new HotkeyPressedEvent((int)m.WParam));
                }
            }

            base.WndProc(ref m);
        }

        public event EventHandler<HotkeyPressedEvent> HotkeyPressed;
    }
}
